package com.jxw.test.application.base.strategy.utils;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.core.env.Environment;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

/**
 * Spel表达式解析器
 */
@Component
@Slf4j
public class SpelUtils implements ApplicationContextAware, EnvironmentAware {

    /**
     * Spel表达式解析器
     */
    private static ExpressionParser expressionParser = new SpelExpressionParser();

    private static ApplicationContext applicationContext;

    private static Environment environment;


    /**
     * 解析Spel表达式
     * @return
     * @param <T>
     */
    public static <T> T parseExpression(String spel, Object data, Class<T> cls, T defaultValue){
        StandardEvaluationContext context = new StandardEvaluationContext();
        context.setVariable("value", data);
        context.setBeanResolver(new BeanFactoryResolver(applicationContext));
        context.setRootObject(environment);
        try {
            Expression expression = expressionParser.parseExpression(spel);
            return expression.getValue(context, cls);
        } catch (Exception e) {
            log.error("Spel表达式解析异常, spel: {}, data: {}", spel, data, e);
            return defaultValue;
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("application设置成功！！！！！");
        SpelUtils.applicationContext = applicationContext;
    }

    /**
     * Set the {@code Environment} that this component runs in.
     *
     * @param environment
     */
    @Override
    public void setEnvironment(Environment environment) {
        SpelUtils.environment = environment;
    }
}
